#include "PDTLinearTraverse.h"
#include "PDTCodeGraph.h"
#include "PDTNode.h"
#include "PDTVar.h"
#include "PDTAssign.h"

// TODO:
// Document:
// ---------
// Abc does not allow initial values to be other than constants

bool isUsedBefore(PDTVar & d, bool & remove) {
    PDTNode * node = d.getNode();
    vector <PDTNode*> & parents = node->getParents();

    PDTNode * pNode = parents[0];
    if (pNode->isAssign()) {
        // parents is an assign statement
        // should check for the following conditions
        // x = x; --> this should be dropped out
        // x = 2; --> return false;
        // y = x; --> return true;
        // x = x + 2; --> return true; this is taken care of 
        PDTAssign * assign = dynamic_cast<PDTAssign*>(pNode);
        assert(assign != NULL);
        
        /* Check for y = x and x = x */
        PDTNode * exp = (PDTNode*)assign->getExpression();
        assert(exp != NULL);
        if (exp == node) {
            // x is on the right hand side of the assign
            PDTVar * trgt = assign->getTarget();
            PDTNode * trgtNode = trgt->getNode();

            if (trgtNode == node) {
                // x = x -> this should be removed
                remove = true;
                return true;
            } else {
                // y = x --> return true
                return true;
            }
        } else {
            // x is certainly on the left hand side
            return false;
        }
    } else { 
        if(pNode->isQuantifier())
            return false;
        return true;
    }
}

PDTLinearTraversalIfc::PDTLinearTraversalIfc(PDTCodeGraph & aOcg): 
    ocg(aOcg) {
}

Traversal::RetType 
PDTLinearTraversalIfc::traverse() {
    for (unsigned int i = 0; i < ocg.nodes.size(); i++) {
        PDTNode * node = ocg.nodes[i];
        if (!node->hasParents()) {
            if (node->traverseEx(*this) == Stop) {
                olog() << "Received Stop signal" << endl;
                stringstream ss;
                node->toString(ss);
                cout << ss.str() << endl;
                return Stop;
            }
        }
    }
    return Continue;
}
